<template>
  <div id="app">
    <div class="header">
      智能害虫识别管理平台
    </div>

    <div class="main-container">
      <div class="upload-section">
        <div class="section-title">
          <i class="el-icon-upload"></i>上传害虫图片
        </div>

        <el-upload
          ref="upload"
          class="drag-upload"
          action=""
          :http-request="handleUpload"
          :on-change="handleFileChange"
          :limit="1"
          :on-exceed="handleExceed"
          drag
          :auto-upload="false"
        >
          <i class="el-icon-upload"></i>
          <div class="el-upload__text">
            拖拽图片到这里，或<em>点击上传</em>
          </div>
          <div class="el-upload__tip" slot="tip">
            支持 JPG/PNG 格式，大小不超过 5MB
          </div>
        </el-upload>

        <div class="input-group">
          <el-input
            v-model="imageUrlInput"
            placeholder="输入图片URL地址"
            clearable
          >
            <template slot="prepend">URL</template>
          </el-input>
          <el-button
            type="primary"
            @click="handleUrlSearch"
            :disabled="!imageUrlInput"
          >
            加载图片
          </el-button>
        </div>

        <div class="action-buttons">
          <el-button
            type="success"
            @click="performRecognition"
            :disabled="!imageUrl"
            :loading="isRecognizing"
          >
            <i class="el-icon-search"></i> 识别害虫
          </el-button>
          <el-button
            type="danger"
            @click="clearAll"
            :disabled="!imageUrl"
          >
            <i class="el-icon-delete"></i> 清空所有
          </el-button>
        </div>
      </div>

      <!-- 修改后的布局结构 -->
      <div class="new-layout-container">
        <!-- 左列：图片预览和趋势图（上下排列） -->
        <div class="left-column">
          <div class="preview-section">
            <div class="section-title">
              <i class="el-icon-picture"></i>待识别图片
            </div>
            <div class="preview-container">
              <img
                v-if="imageUrl"
                :src="imageUrl"
                alt="预览图"
              />
              <div v-else class="no-content">
                <i class="el-icon-picture-outline" style="font-size: 48px; margin-bottom: 15px;"></i>
                <p>请上传或输入图片URL</p>
              </div>
            </div>
          </div>

          <!-- 害虫频率趋势图移动到左列下方 -->
          <div class="trend-section">
            <div class="section-title">
              <i class="el-icon-trend-chart"></i>害虫频率趋势图
            </div>
            <div ref="chart" class="chart-container"></div>
          </div>
        </div>

        <!-- 右列：识别结果 -->
        <div class="right-column">
          <div class="result-section">
            <div class="section-title">
              <i class="el-icon-document"></i>识别结果
            </div>
            <div class="result-container">
              <div class="result-content">
                <img
                  v-if="resultImage"
                  :src="resultImage"
                  alt="识别结果"
                  style="max-height: 200px; margin-bottom: 20px;"
                />

                <div v-if="recognitionResult" class="result-text">
                  <div class="result-item">
                    <span class="insect-name">害虫类型：</span> {{ recognitionResult.type }}
                  </div>
                  <div class="result-item">
                    <span class="confidence">置信度：</span> {{ recognitionResult.confidence }}%
                  </div>
                  <div class="result-item">
                    <span>检测时间：</span> {{ (recognitionResult.time || 0).toFixed(1) }}ms
                  </div>
                  <div class="result-item">
                    <span>目标数量：</span> {{ recognitionResult.count }} 个
                  </div>
                  <div class="result-item">
                    <span>目标位置：</span>
                    <div class="position-details">
                      <div v-for="(pos, index) in recognitionResult.positions" :key="index" class="position-item">
                        目标 {{index + 1}}: (x: {{pos[0].toFixed(1)}}, y: {{pos[1].toFixed(1)}})
                      </div>
                    </div>
                  </div>
                  <div class="result-item">
                    <span>危害等级：</span>
                    <el-tag :type="recognitionResult.severity === '高' ? 'danger' : recognitionResult.severity === '中' ? 'warning' : 'success'">
                      {{ recognitionResult.severity }}
                    </el-tag>
                  </div>
                  <div class="result-item" style="margin-top: 15px;">
                    <span style="font-weight: 600; color: #f56c6c;">防治建议：</span>
                    {{ recognitionResult.suggestion }}
                  </div>
                </div>

                <div v-else-if="isRecognizing" class="loading-container">
                  <div class="loading-spinner"></div>
                  <p>正在识别中，请稍候...</p>
                </div>

                <div v-else class="no-content">
                  <i class="el-icon-search" style="font-size: 48px; margin-bottom: 15px;"></i>
                  <p>识别结果将显示在这里</p>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div class="stats-section">
        <div class="section-title">
          <i class="el-icon-data-analysis"></i>系统统计
        </div>
        <div class="stats-grid">
          <div class="stat-card">
            <i class="el-icon-picture" style="font-size: 36px; color: #409EFF;"></i>
            <div class="stat-value">{{ stats.totalImages }}</div>
            <div class="stat-label">已处理图片</div>
          </div>
          <div class="stat-card">
            <i class="el-icon-bug" style="font-size: 36px; color: #67c23a;"></i>
            <div class="stat-value">{{ stats.totalInsects }}</div>
            <div class="stat-label">识别害虫总数</div>
          </div>
          <div class="stat-card">
            <i class="el-icon-time" style="font-size: 36px; color: #e6a23c;"></i>
            <div class="stat-value">{{ stats.avgTime }}ms</div>
            <div class="stat-label">平均识别时间</div>
          </div>
          <div class="stat-card">
            <i class="el-icon-success" style="font-size: 36px; color: #f56c6c;"></i>
            <div class="stat-value">{{ stats.accuracy }}%</div>
            <div class="stat-label">识别准确率</div>
          </div>
        </div>
      </div>
    </div>

    <div class="footer">
      <p>虫眼通 v1.0 © 2025 厦门工学院 | 基于 YOLOv8 的虫害检测技术</p>
    </div>
  </div>
</template>

<script>
import axios from 'axios';
import * as echarts from 'echarts';

export default {
  name: 'InsectRecognition',
  data() {
    return {
      imageUrl: '',
      imageUrlInput: '',
      recognitionResult: null,
      resultImage: '',
      isRecognizing: false,
      stats: {
        totalImages: 1284,
        totalInsects: 5267,
        avgTime: 52.7,
        accuracy: 93.5
      },
      apiBaseUrl: 'http://127.0.0.1:5000',

      // 害虫频率趋势图数据
      chart: null,
      option: {
        title: {
          text: '害虫频率趋势图',
          left: 'center'
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {type: 'cross'}
        },
        legend: {
          data: [],
          top: 30
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '15%',  // 为图例留出空间
          containLabel: true
        },
        xAxis: [{
          type: 'category',
          boundaryGap: false,
          data: []
        }],
        yAxis: [{
          type: 'value',
          axisLabel: {
            formatter: '{value}'
          }
        }],
        series: []
      }
    };
  },
  async mounted() {
    await this.fetchTrendData();
    this.initChart();
    window.addEventListener('resize', this.handleResize);
  },
  beforeUnmount() {
    if (this.chart) {
      this.chart.dispose();
    }
    window.removeEventListener('resize', this.handleResize);
  },
  methods: {
    // 害虫频率趋势图方法
    async fetchTrendData() {
      try {
        const response = await axios.get('http://localhost:8088/api/chart/pest-trend');
        console.log('API响应数据:', response.data);

        // 数据转换关键步骤
        this.option.xAxis[0].data = response.data.months;
        this.option.legend.data = response.data.series.map(item => item.name);

        this.option.series = response.data.series.map(item => ({
          name: item.name,
          type: 'line',
          stack: 'Total',  // 确保堆叠模式开启
          areaStyle: {
            opacity: 0.8  // 增加区域透明度
          },
          emphasis: {
            focus: 'series'
          },
          data: item.data,
          smooth: true  // 添加平滑曲线
        }));

        console.log('最终图表配置:', this.option);
      } catch (error) {
        console.error('数据获取失败:', error);
        // 使用模拟数据作为后备
        this.useMockTrendData();
      }
    },
    initChart() {
      if (!this.chart) {
        this.chart = echarts.init(this.$refs.chart);
      }
      this.chart.setOption(this.option);

      // 调试用：检查实际渲染配置
      setTimeout(() => {
        const currentOption = this.chart.getOption();
        console.log('当前渲染配置:', currentOption);
      }, 500);
    },
    handleResize() {
      if (this.chart) {
        setTimeout(() => {
          this.chart.resize();
          console.log('图表已重绘');
        }, 300);
      }
    },
    useMockTrendData() {
      // 模拟数据作为后备
      const mockData = {
        months: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
        series: [
          {
            name: '棉铃虫',
            data: [120, 132, 101, 134, 90, 230, 210, 182, 191, 234, 290, 330]
          },
          {
            name: '稻飞虱',
            data: [220, 182, 191, 234, 290, 330, 310, 201, 154, 190, 330, 410]
          },
          {
            name: '二化螟',
            data: [150, 232, 201, 154, 190, 330, 410, 320, 280, 310, 250, 190]
          }
        ]
      };

      this.option.xAxis[0].data = mockData.months;
      this.option.legend.data = mockData.series.map(item => item.name);

      this.option.series = mockData.series.map(item => ({
        name: item.name,
        type: 'line',
        stack: 'Total',
        areaStyle: {
          opacity: 0.8
        },
        emphasis: {
          focus: 'series'
        },
        data: item.data,
        smooth: true
      }));

      console.log('使用模拟数据:', this.option);
    },

    // 害虫识别相关方法
    handleUpload(request) {
      const file = request.file;
      return new Promise((resolve) => {
        const reader = new FileReader();
        reader.onload = (e) => {
          this.imageUrl = e.target.result;
          resolve();
        };
        reader.readAsDataURL(file);
      });
    },
    handleFileChange(file, fileList) {
      if (fileList.length > 0) {
        this.handleUpload({file: fileList[0].raw});
      }
    },
    handleExceed() {
      this.$message.warning('每次只能上传一张图片');
    },
    handleUrlSearch() {
      this.imageUrl = this.imageUrlInput;
    },
    async performRecognition() {
      if (!this.imageUrl) {
        this.$message.warning('请先上传图片');
        return;
      }

      this.isRecognizing = true;
      this.recognitionResult = null;
      this.resultImage = '';

      try {
        const base64Data = this.imageUrl.split(',')[1];
        const byteString = atob(base64Data);
        const mimeString = this.imageUrl.split(',')[0].split(':')[1].split(';')[0];
        const ab = new ArrayBuffer(byteString.length);
        const ia = new Uint8Array(ab);
        for (let i = 0; i < byteString.length; i++) {
          ia[i] = byteString.charCodeAt(i);
        }
        const blob = new Blob([ab], { type: mimeString });

        const formData = new FormData();
        const fileName = `upload_${Date.now()}.jpg`;
        formData.append('file', blob, fileName);

        const response = await axios.post(`${this.apiBaseUrl}/predict`, formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        });

        if (response.data && response.data.success) {
          this.stats.totalImages += 1;
          this.stats.totalInsects += response.data.data.predictions.length;

          this.resultImage = response.data.data.image;

          if (response.data.data.predictions && response.data.data.predictions.length > 0) {
            const predictions = response.data.data.predictions;
            this.recognitionResult = {
              type: predictions[0].class || '未知害虫',
              confidence: (predictions[0].confidence * 100).toFixed(1),
              time: response.data.data.inference_time || 0,
              count: predictions.length,
              positions: predictions.map(p => p.box),
              severity: this.getSeverityLevel(predictions[0].confidence),
              suggestion: this.getSuggestion(predictions[0].class || '未知害虫')
            };
          }

          this.$message.success('识别完成！');
        } else {
          throw new Error('无效的API响应');
        }
      } catch (error) {
        console.error('识别过程中发生错误:', error);
        this.$message.error(`识别失败: ${error.message}`);
        this.useMockData();
      } finally {
        this.isRecognizing = false;
      }
    },
    getSeverityLevel(confidence) {
      if (typeof confidence === 'number') {
        if (confidence > 0.85) {
          return '高';
        } else if (confidence > 0.70) {
          return '中';
        } else {
          return '低';
        }
      } else if (typeof confidence === 'string') {
        const confidenceNum = parseFloat(confidence);
        if (confidenceNum > 85) {
          return '高';
        } else if (confidenceNum > 70) {
          return '中';
        } else {
          return '低';
        }
      }
      return '低';
    },
    getSuggestion(pestType) {
      const suggestions = {
        '棉铃虫': '使用高效氯氰菊酯喷雾，每周一次，连续三周',
        '稻飞虱': '喷洒吡虫啉可湿性粉剂，注意叶面背面也要喷洒',
        '二化螟': '使用苏云金杆菌制剂进行生物防治',
        '玉米螟': '在成虫羽化期使用性诱剂诱杀',
        '小菜蛾': '使用阿维菌素乳油进行喷洒，注意轮换用药',
        '蚜虫': '释放瓢虫等天敌进行生物防治',
        '红蜘蛛': '使用螺螨酯悬浮剂进行喷洒，重点喷洒叶背面',
        '白粉虱': '使用噻虫嗪水分散粒剂进行防治',
        '稻纵卷叶螟': '使用氯虫苯甲酰胺悬浮剂进行喷洒',
        '草地贪夜蛾': '使用甲维盐和茚虫威复配制剂进行防治',
        '未知害虫': '请咨询农业专家进行鉴定和防治'
      };
      return suggestions[pestType] || '请咨询农业专家进行鉴定和防治';
    },
    useMockData() {
      const insectTypes = ['棉铃虫', '稻飞虱', '二化螟', '玉米螟', '小菜蛾', '蚜虫', '红蜘蛛', '白粉虱', '稻纵卷叶螟', '草地贪夜蛾'];
      const suggestions = [
        '使用高效氯氰菊酯喷雾，每周一次，连续三周',
        '喷洒吡虫啉可湿性粉剂，注意叶面背面也要喷洒',
        '使用苏云金杆菌制剂进行生物防治',
        '在成虫羽化期使用性诱剂诱杀',
        '使用阿维菌素乳油进行喷洒，注意轮换用药',
        '释放瓢虫等天敌进行生物防治',
        '使用螺螨酯悬浮剂进行喷洒，重点喷洒叶背面',
        '使用噻虫嗪水分散粒剂进行防治',
        '使用氯虫苯甲酰胺悬浮剂进行喷洒',
        '使用甲维盐和茚虫威复配制剂进行防治',
        '请咨询农业专家进行鉴定和防治'
      ];
      const severityLevels = ['低', '中', '高'];
      const randomType = insectTypes[Math.floor(Math.random() * insectTypes.length)];
      const confidence = (Math.random() * 30 + 70).toFixed(1);
      const time = Math.floor(Math.random() * 30 + 45);
      const severity = severityLevels[Math.floor(Math.random() * severityLevels.length)];
      const suggestion = suggestions[Math.floor(Math.random() * suggestions.length)];

      this.recognitionResult = {
        type: randomType,
        confidence: confidence,
        time: time,
        severity: severity,
        suggestion: suggestion
      };
      this.resultImage = this.imageUrl;
      this.$message.warning('识别失败，已使用模拟数据作为后备方案');
    },
    clearAll() {
      this.imageUrl = '';
      this.imageUrlInput = '';
      this.recognitionResult = null;
      this.resultImage = '';
      this.$refs.upload.clearFiles();
      this.$message.info('已清空所有内容');
    }
  }
};
</script>

<style scoped>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;
}

body {
  background-color: #f5f7fa;
  color: #333;
  padding: 0 20px;
}

#app {
  max-width: 1400px;
  margin: 0 auto;
  padding-bottom: 40px;
}

.header {
  background: linear-gradient(135deg, #409EFF, #64b5f6);
  color: white;
  font-size: 28px;
  height: 80px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 0 0 12px 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  margin-bottom: 30px;
  position: relative;
  overflow: hidden;
}

.header::before {
  content: "";
  position: absolute;
  top: -50%;
  left: -50%;
  width: 200%;
  height: 200%;
  background: radial-gradient(circle, rgba(255,255,255,0.2) 0%, rgba(255,255,255,0) 70%);
  transform: rotate(30deg);
}

.main-container {
  display: flex;
  flex-direction: column;
  gap: 30px;
}

.upload-section {
  background-color: #fff;
  padding: 30px;
  border-radius: 12px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
  transition: all 0.3s ease;
}

.upload-section:hover {
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}

.section-title {
  font-size: 20px;
  font-weight: 600;
  color: #333;
  margin-bottom: 20px;
  padding-bottom: 12px;
  border-bottom: 2px solid #409EFF;
  display: flex;
  align-items: center;
}

.section-title i {
  margin-right: 10px;
  color: #409EFF;
}

.drag-upload {
  text-align: center;
  padding: 30px 20px;
  border: 2px dashed #dcdfe6;
  border-radius: 8px;
  background-color: #fafafa;
  transition: all 0.3s;
  cursor: pointer;
}

.drag-upload:hover {
  border-color: #409EFF;
  background-color: #f0f7ff;
}

.el-icon-upload {
  font-size: 48px;
  color: #409EFF;
  margin-bottom: 15px;
}

.el-upload__text {
  font-size: 16px;
  color: #606266;
  margin: 15px 0;
}

.el-upload__text em {
  color: #409EFF;
  font-style: normal;
  font-weight: 600;
}

.input-group {
  display: flex;
  gap: 15px;
  margin-top: 25px;
}

.action-buttons {
  display: flex;
  gap: 15px;
  justify-content: center;
  margin-top: 25px;
}

.el-button--success {
  background: linear-gradient(135deg, #67c23a, #85ce61);
  border: none;
  font-weight: 600;
  transition: all 0.3s;
}

.el-button--success:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(103, 194, 58, 0.3);
}

.el-button--danger {
  background: linear-gradient(135deg, #f56c6c, #f78989);
  border: none;
  font-weight: 600;
  transition: all 0.3s;
}

.el-button--danger:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(245, 108, 108, 0.3);
}

/* 新的布局样式 */
.new-layout-container {
  display: flex;
  gap: 30px;
  margin-bottom: 30px;
}

.left-column {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 30px;
}

.right-column {
  flex: 1;
}

/* 趋势图现在在左列 */
.trend-section {
  background-color: #fff;
  padding: 25px;
  border-radius: 12px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
  height: 500px;
}

/* 识别结果现在在右列 */
.result-section {
  background-color: #fff;
  border-radius: 12px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
  padding: 25px;
  transition: all 0.3s ease;
  height: 930px;
}

.result-section:hover {
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}

/* 害虫频率趋势图样式 */
.chart-container {
  width: 100%;
  height: 400px; /* 适当调整高度 */
  min-width: 300px;
  background: #fff;
}

.preview-section {
  background-color: #fff;
  border-radius: 12px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
  padding: 25px;
  transition: all 0.3s ease;
  height: 400px;
}

.preview-section:hover {
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}

.preview-container, .result-container {
  padding: 20px;
  min-height: 300px;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 8px;
  background-color: #fafafa;
  border: 1px solid #ebeef5;
}

.preview-container img, .result-container img {
  max-width: 100%;
  max-height: 250px;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  object-fit: contain;
}

.result-content {
  width: 100%;
}

.result-text {
  white-space: pre-wrap;
  word-wrap: break-word;
  text-align: left;
  font-size: 16px;
  line-height: 1.8;
  padding: 15px;
  background-color: #f8f9fa;
  border-radius: 8px;
  border-left: 4px solid #409EFF;
  margin-top: 20px;
}

.result-item {
  padding: 8px 0;
  border-bottom: 1px dashed #eaeaea;
}

.result-item:last-child {
  border-bottom: none;
}

.insect-name {
  font-weight: 600;
  color: #409EFF;
}

.confidence {
  color: #67c23a;
  font-weight: 600;
}

.no-content {
  color: #999;
  font-size: 16px;
  text-align: center;
}

.loading-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
}

.loading-spinner {
  width: 50px;
  height: 50px;
  border: 5px solid #f3f3f3;
  border-top: 5px solid #409EFF;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.stats-section {
  background-color: #fff;
  padding: 25px;
  border-radius: 12px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
}

.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 20px;
  margin-top: 15px;
}

.stat-card {
  background: linear-gradient(135deg, #f0f7ff, #e1f0ff);
  border-radius: 10px;
  padding: 20px;
  text-align: center;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05);
}

.stat-value {
  font-size: 32px;
  font-weight: 700;
  color: #409EFF;
  margin: 10px 0;
}

.stat-label {
  font-size: 16px;
  color: #606266;
}

.footer {
  text-align: center;
  margin-top: 40px;
  color: #909399;
  font-size: 14px;
  padding: 20px 0;
  border-top: 1px solid #ebeef5;
}

.position-details {
  margin-top: 8px;
  padding: 8px;
  background-color: #f5f7fa;
  border-radius: 4px;
}

.position-item {
  font-size: 14px;
  color: #606266;
  padding: 4px 0;
  border-bottom: 1px dashed #eaeaea;
}

.position-item:last-child {
  border-bottom: none;
}

/* 响应式布局 */
@media (max-width: 992px) {
  .new-layout-container {
    flex-direction: column;
  }

  .left-column {
    order: 1;
  }

  .right-column {
    order: 2;
  }
}

@media (max-width: 768px) {
  .input-group {
    flex-direction: column;
  }

  .action-buttons {
    flex-direction: column;
    align-items: center;
  }

  .el-button {
    width: 100%;
  }

  .header {
    font-size: 20px;
    height: 60px;
  }

  .preview-container, .result-container {
    min-height: 250px;
  }

  .trend-section {
    min-height: 400px;
  }

  .chart-container {
    height: 400px;
  }
}
</style>
